<?php
  class Timer{
    private $array_laps;
    private $array_integrity;
    const LABEL_GO = 'g';
    const LABEL_STOP = 's';

    //
    // contruct, get, set
    //

    public function __construct(){
      $this->array_laps = array(array());
      $this->array_integrity = array(array());
    }

    public function get_label_go(){
      return self::LABEL_GO;
    }

    public function get_label_stop(){
      return self::LABEL_STOP;
    }

    public function get_current_lap(){
      $nb_lap = count($this->array_laps);
      return $this->array_laps[$nb_lap-1];
    }

    //
    // special get
    //

    public function get_sum_lap_detail(){
      $res = array();
      foreach($this->array_laps as $lap){
        $res[] = self::sum_lap_detail($lap);
      }
      return $res;
    }

    private static function sum_lap_detail(&$lap){
      $nb_time = count($lap);
      $array_sum = array();
      for($i=0; $i<$nb_time; $i+=2){
        $array_sum[]= $lap[$i+1] - $lap[$i];
      }
      return $array_sum;
    }

    public function get_sum_lap(){
      $res = array();
      foreach($this->array_laps as $lap){
        $res[] = self::sum_lap($lap);
      }
      return $res;
    }

    private static function sum_lap(&$lap){
      $nb_time = count($lap);
      $sum = 0;
      for($i=0; $i<$nb_time; $i+=2){
        $sum += $lap[$i+1] - $lap[$i];
      }
      return $sum;
    }

    public function get_average(){
      $res = $this->get_sum_lap();
      return array_sum($res) / count($res);
    }

    public function get_average_each(){
      $res = $this->get_sum_lap_detail();
      $array_res = array();
      foreach($res as $i=>$r){
        $array_res[$i] = array_sum($r) / count($r);
      }
      return $array_res;
    }

    //
    // Basics commands
    //

    public function go(){
      $nb_laps = count($this->array_laps);
      $this->array_integrity[$nb_laps-1][] = self::LABEL_GO;
      $this->array_laps[$nb_laps-1][] = microtime(true);
    }

    public function stop(){
      $nb_laps = count($this->array_laps);
      $this->array_integrity[$nb_laps-1][] = self::LABEL_STOP;
      $this->array_laps[$nb_laps-1][] = microtime(true);
    }

    public function new_lap(){
      $this->array_laps[] = array();
      $this->array_integrity[] = array();
    }

    public function new_lap_and_go(){
      $this->new_lap();
      $this->go();
    }

    //
    // check integrity : check if all the records are well-formed
    //

    public function check_integrity(){
      $c_integrity = count($this->array_integrity);
      if(count($this->array_laps) != $c_integrity){
        die('Timer::check_integrity DIFF_COUNT');
      }

      for($i=0;$i<$c_integrity;++$i){
        self::check_integrity_array($this->array_integrity[$i]);
      }
      return true;
    }

    private static function check_integrity_array(&$_a){
      $c = count($_a);
      if(($c%2) != 0){
        die('Timer::check_integrity NOT_PAIR');
      }
      $nb_g = $nb_s = 0;
      for($i=0; $i<$c; ++$i){
        if(self::LABEL_GO === $_a[$i]){
          ++$nb_g;
        }
        elseif(self::LABEL_STOP === $_a[$i]){
          ++$nb_s;
        }
        else{
          die('Timer::check_integrity_array LABEL_UNKNOWN');
        }
      }
      return true;
    }
  }

?>
